package com.rockcent.wechat.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.helper.MallFundHelper;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.*;
import com.rockcent.mall.lib.dto.CustomerDto;
import com.rockcent.mall.lib.dto.MallOrderDto;
import com.rockcent.mall.lib.dto.MallOrderPaymentDto;
import com.rockcent.mall.lib.helper.*;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.service.PaymentService;
import com.rockcent.wechat.Config;
import com.rockcent.wechat.Prop;
import com.rockcent.wechat.helper.*;
import com.rockcent.wechat.Routes;
import com.rockcent.wechat.payment.WechatPaymentAttach;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpPayService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.rockcent.wechat.helper.WechatHelper.sToken;
import static java.util.stream.Stream.of;

/**
 * Created by HK on 16/10/27.
 */
@Controller
@RequestMapping(value = Routes.API_PREFIX)
public class PaymentController {

    private final Logger log = LoggerFactory.getLogger(PaymentController.class);

    @Autowired
    private CustomerHelper customerHelper;
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    private MallOrderPaymentHelper mallOrderPaymentHelper;
    @Autowired
    private MallOrderRepository mallOrderRepository;
    @Autowired
    private WechatHelper wechatHelper;
    @Autowired
    private MallOrderPaymentRepository mallOrderPaymentRepository;
    @Autowired
    private MallOrderPaymentFlowRepository mallOrderPaymentFlowRepository;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MerchantOrderRepository merchantOrderRepository;
    @Autowired
    private CustomerFundRepository customerFundRepository;
    @Autowired
    private MallFundRepository mallFundRepository;
    @Autowired
    private CustomerFundFlowRepository customerFundFlowRepository;
    @Autowired
    private MallFundFlowRepository mallFundFlowRepository;
    @Autowired
    private Prop prop;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private MallCashCouponFlowRepository mallCashCouponFlowRepository;
    @Autowired
    private MiniAppConfigRepository miniAppConfigRepository;


    /**
     *
     * @api {post} /api/v2/payment/balance 支付 余额支付
     * @apiGroup payment
     * @apiVersion 1.0.0
     * @apiHeader {String} domain <code>必须参数</code>域名
     * @apiHeader {String} userToken <code>必须参数</code>userToken
     *
     * @apiParam {String} mallOrderNum 平台订单号
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @RequestMapping(value = "/payment/balance", method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public JsonResult paymentBalance(@RequestBody MallOrderPaymentDto dto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(dto.getMallOrderNum())) {
                jsonResult.errorParam(MallOrder.CHECK_ORDER_NUM_IS_NOT_NULL, log);
                return;
            }

            Customer customer = customerRepository.findOne(customerDto.getId());
            if (customer == null) {
                jsonResult.remind("用户账号异常, 不能支付", log);
                return;
            }

            MallOrder mallOrder = mallOrderRepository.findByOrderNum(dto.getMallOrderNum());
            if (mallOrder == null) {
                jsonResult.remind(MallOrder.REMIND_RECORD_IS_NOT_EXIST,log);;
                return;
            }
            if (mallOrder.getStatus() != MallOrderStatus.WAIT_PAYING) {
                jsonResult.remind("订单状态异常，不能支付", log);
                return;
            }


            // 用户资金
            CustomerFund customerFund = customerFundRepository.findOne(customer.getCustomerFundId());
            // 当余额少于实付金额
            if (customerFund.getAvailableAmount().compareTo(mallOrder.getActualAmount()) == -1) {
                jsonResult.remind("余额少于实付金额不能使用余额支付",log);
                return;
            }

            // 创建平台订单支付
            MallOrderPayment mallOrderPayment = mallOrderPaymentHelper.create(OrderHelper.SINGLEONE.genMallOrderPaymentNumber(), mallOrder.getActualAmount(), mallOrder.getMallId(), mallOrder.getId(), mallOrder.getOrderNum(), customerDto.getId(), MallOrderPaymentStatus.SUCCESS);
            mallOrderPayment = mallOrderPaymentRepository.save(mallOrderPayment);

            // 添加支付流水
            MallOrderPaymentFlow mallOrderPaymentFlow = new MallOrderPaymentFlow();
            mallOrderPaymentFlow.setFlowNum(OrderHelper.SINGLEONE.genMallOrderPaymentFlowNumber());
            mallOrderPaymentFlow.setPaymentNum(mallOrderPayment.getPaymentNum());
            mallOrderPaymentFlow.setCustomerId(customerDto.getId());
            mallOrderPaymentFlow.setMallOrderId(mallOrder.getId());
            mallOrderPaymentFlow.setMallOrderNum(mallOrder.getOrderNum());
            mallOrderPaymentFlow.setMallId(mallOrder.getMallId());
            mallOrderPaymentFlow.setAmount(mallOrder.getActualAmount());
            mallOrderPaymentFlow.setPaymentMethod(PaymentMethod.BALANCE);
            mallOrderPaymentFlow.setStatus(MallOrderPaymentStatus.SUCCESS); // 支付成功
            mallOrderPaymentFlowRepository.save(mallOrderPaymentFlow);

            OrderStatusHelper.SINGLETON.mallOrderPayed(mallOrder); //修改平台订单为已支付
            mallOrder.setPaymentMethod(PaymentMethod.BALANCE);
            mallOrderRepository.save(mallOrder);

            List<MerchantOrder> merchantOrderList = merchantOrderRepository.findByMallOrderNum(mallOrder.getOrderNum());
            // 支付成功 修改商家订单
            paymentService.modifyMerchantOrder(mallOrder,merchantOrderList);

            // 用户余额支付
            CustomerFundFlow expendCustomerFundFlow = CustomerFundFlowHelper.SINGLEONE.create(customerFund, mallOrder, mallOrder.getActualAmount(), BigDecimal.ZERO, mallOrder.getActualAmount(), FundTransactionFlow.EXPEND, CustomerFundFlowTransactionType.BALANCE_EXPEND, CustomerFundFlowTransactionType.BALANCE_EXPEND.getValue(), PaymentMethod.BALANCE);
            customerFund.setAvailableAmount(expendCustomerFundFlow.getAvailableAmount());
            customerFund.setFrozen(expendCustomerFundFlow.getFrozen());
            customerFund.setTotalAmount(expendCustomerFundFlow.getAvailableAmount().add(expendCustomerFundFlow.getFrozen()));
            customerFundFlowRepository.save(expendCustomerFundFlow);
            // 平台资金流
            MallFund mallFund = mallFundRepository.findOne(mallOrder.getMallFundId());

            // 平台冻结资金加 用户余额支付
            MallFundFlow balanceMallFundFlow = MallFundFlowHelper.SINGLEONE.create(mallFund, mallOrder.getOrderNum(), BigDecimal.ZERO, mallOrder.getActualAmount(), mallOrder.getActualAmount(), FundTransactionFlow.INCOME, MallFundFlowTransactionType.F_BALANCE_SUCCESS_FROZEN, PaymentMethod.BALANCE, null);
            balanceMallFundFlow = mallFundFlowRepository.save(balanceMallFundFlow);
            balanceMallFundFlow.setParentId(balanceMallFundFlow.getId());
            MallFundHelper.SINGLEONE.calculationMallFundAmount(mallFund, balanceMallFundFlow.getFrozen(), balanceMallFundFlow.getAvailableAmount());


            // 使用现金券
            if (mallOrder.getCashCouponId() != null) {
                // 现金券余额减 流水
                MallCashCouponFlow mallCashCouponFlow = new MallCashCouponFlow();
                mallCashCouponFlow.setCashCouponId(mallOrder.getCashCouponId());
                mallCashCouponFlow.setMallId(mallOrder.getMallId());
                mallCashCouponFlow.setTransactionFlow(FundTransactionFlow.EXPEND);
                mallCashCouponFlow.setOperationAmount(mallOrder.getCashCouponAmount());
                mallCashCouponFlowRepository.save(mallCashCouponFlow);
                // 平台现金券减
                mallFund.setAvailableCashAmount(mallFund.getAvailableCashAmount().subtract(mallOrder.getCashCouponAmount()));

                // 平台冻结资金加 现金券支付
                MallFundFlow cashCouponMallFundFlow = MallFundFlowHelper.SINGLEONE.create(mallFund, mallOrder.getOrderNum(), BigDecimal.ZERO, mallOrder.getCashCouponAmount().subtract(mallOrder.getCashCouponSurplusAmount()), mallOrder.getCashCouponAmount().subtract(mallOrder.getCashCouponSurplusAmount()), FundTransactionFlow.INCOME, MallFundFlowTransactionType.F_CASH_COUPON_SUCCESS_FROZEN, PaymentMethod.CASH_COUPON, null, balanceMallFundFlow.getParentId());
                cashCouponMallFundFlow = mallFundFlowRepository.save(cashCouponMallFundFlow);
                MallFundHelper.SINGLEONE.calculationMallFundAmount(mallFund, cashCouponMallFundFlow.getFrozen(), cashCouponMallFundFlow.getAvailableAmount());
                // 订单 现金券剩余金额 > 0
                if (mallOrder.getCashCouponSurplusAmount().compareTo(BigDecimal.ZERO) == 1) {
                    // 平台冻结资金加 现金券多出部分
                    MallFundFlow surplusCashCouponMallFundFlow = MallFundFlowHelper.SINGLEONE.create(mallFund, mallOrder.getOrderNum(), BigDecimal.ZERO, mallOrder.getCashCouponSurplusAmount(), mallOrder.getCashCouponSurplusAmount(), FundTransactionFlow.INCOME, MallFundFlowTransactionType.F_CASH_COUPON_SURPLUS_SUCCESS_FROZEN_INCOME, PaymentMethod.CASH_COUPON, null, balanceMallFundFlow.getParentId());
                    surplusCashCouponMallFundFlow = mallFundFlowRepository.save(surplusCashCouponMallFundFlow);
                    MallFundHelper.SINGLEONE.calculationMallFundAmount(mallFund, surplusCashCouponMallFundFlow.getFrozen(), surplusCashCouponMallFundFlow.getAvailableAmount());
                }
            }

            // 平台资金账户
            mallFundRepository.save(mallFund);

            // 当服务订单内包含不可退产品支付成功,马上结算
            paymentService.productServiceSettled(mallOrder, merchantOrderList);

            // 如果购买礼包赠送卡券时，支付成功把卡券赠送到用户
            paymentService.giftGiveCoupon(mallOrder);
            MallOrderDto mallOrderDto = new MallOrderDto();
            mallOrderDto.setOrderNum(mallOrder.getOrderNum());
            jsonResult.data = mallOrderDto;


        };
        return doing.go(dto, customerDto, request, objectMapper, log);
    }

    /**
     * @api {post} /api/v2/payment/wechat 支付 微信支付
     * @apiGroup payment
     * @apiVersion 1.0.0
     * @apiHeader {String} domain <code>必须参数</code>域名
     * @apiHeader {String} userToken <code>必须参数</code>userToken
     *
     * @apiParam {String} mallOrderNum 平台订单号
     * @apiParam {String} orderSource 订单来源，WXAPP:微信小程序；WEXIN:公众号H5
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data":{
     *      "appId":"wxce62f97f15d07734",
     *      "timeStamp":17585882354,'
     *      "nonceStr":"nonceStr",
     *      "package":"prepay_id=xxxxx",
     *      "signType":"MD5",
     *      "paySign":"123xcvdgasfrsfsaf"
     *  }
     * }
     *
     */
    @RequestMapping(value = "/payment/wechat", method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public JsonResult paymentWechat(@RequestBody MallOrderPaymentDto dto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        Customer customer = customerRepository.findOne(customerDto.getId());
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(dto.getMallOrderNum())) {
                jsonResult.errorParam("平台订单号 不能为空", log);
                return;
            }
            MallOrder mallOrder = mallOrderRepository.findByOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrder == null) {
                jsonResult.remind(MallOrder.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            if (mallOrder.getActualAmount().doubleValue() == 0) {
                jsonResult.remind("实付金额为0时，不能使用微信支付",log);
                return;
            }


            // 创建平台订单支付
            MallOrderPayment mallOrderPayment = mallOrderPaymentRepository.findByMallOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrderPayment == null) {
                mallOrderPayment = mallOrderPaymentHelper.create(OrderHelper.SINGLEONE.genMallOrderPaymentNumber(), mallOrder.getActualAmount(), mallOrder.getMallId(), mallOrder.getId(), mallOrder.getOrderNum(), customerDto.getId());
                mallOrderPayment = mallOrderPaymentRepository.save(mallOrderPayment);
            }

            if (mallOrderPayment.getStatus() != MallOrderPaymentStatus.WAIT) {
                jsonResult.remind("该订单状态异常,不能继续支付", log);
                return;
            }

            // 添加支付流水
            MallOrderPaymentFlow mallOrderPaymentFlow = new MallOrderPaymentFlow();
            mallOrderPaymentFlow.setFlowNum(OrderHelper.SINGLEONE.genMallOrderPaymentFlowNumber());
            mallOrderPaymentFlow.setPaymentNum(mallOrderPayment.getPaymentNum());
            mallOrderPaymentFlow.setCustomerId(customerDto.getId());
            mallOrderPaymentFlow.setMallOrderId(mallOrder.getId());
            mallOrderPaymentFlow.setMallOrderNum(mallOrder.getOrderNum());
            mallOrderPaymentFlow.setMallId(mallOrder.getMallId());
            mallOrderPaymentFlow.setAmount(mallOrder.getActualAmount());
            mallOrderPaymentFlow.setPaymentMethod(PaymentMethod.WECHAT);
            mallOrderPaymentFlow.setStatus(MallOrderPaymentStatus.WAIT); // 支付中
            mallOrderPaymentFlowRepository.save(mallOrderPaymentFlow);


            WxMpService wxMpService = wechatHelper.getWxMpService(customerDto.getMallCustomerDomain());
            //默认微信支付

            WechatPaymentAttach wechatPaymentAttach = new WechatPaymentAttach();
            wechatPaymentAttach.setDomain(customerDto.getMallCustomerDomain());
            stringRedisTemplate.opsForValue().set("wechat_payment_code_" + wechatPaymentAttach.getCode(), wechatPaymentAttach.getCode());
            stringRedisTemplate.expire("wechat_payment_code_" + wechatPaymentAttach.getCode(), 2, TimeUnit.DAYS); // 有效时间2天

            WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
            wxPayUnifiedOrderRequest.setBody("微信支付 订单号 : " + mallOrder.getOrderNum());
            wxPayUnifiedOrderRequest.setOutTradeNo(mallOrderPaymentFlow.getFlowNum());
            // 微信 total_fee 单位为分
            wxPayUnifiedOrderRequest.setTotalFee(mallOrder.getActualAmount().multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
            wxPayUnifiedOrderRequest.setSpbillCreateIp(request.getRemoteHost());
            wxPayUnifiedOrderRequest.setNotifyURL(prop.paymentNotifyUrlWechat);
            wxPayUnifiedOrderRequest.setTradeType("JSAPI");
            wxPayUnifiedOrderRequest.setAttach(objectMapper.writeValueAsString(wechatPaymentAttach));
            wxPayUnifiedOrderRequest.setOpenid(customer.getWechatOpenId());


            Map<String, String> callPayParams = wxMpService.getPayService().getPayInfo(wxPayUnifiedOrderRequest);

//            String callPayParamsJson = objectMapper.writeValueAsString(callPayParams);
            jsonResult.data = callPayParams;
        };

        return doing.go(null, customerDto, request, objectMapper, log);
    }

    /**
     * @api {post} /api/v2/payment/wechat_simulation 支付 微信模拟支付
     * @apiGroup payment
     * @apiVersion 1.0.0
     * @apiHeader {String} domain <code>必须参数</code>域名
     * @apiHeader {String} userToken <code>必须参数</code>userToken
     *
     * @apiParam {String} mallOrderNum 平台订单号
     *
     * @apiParamExample {json} 微信模拟支付:
     * {
     *  "mallOrderNum":"201611071420077718425294"
     * }
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  "data":
     * }
     *
     */
    @RequestMapping(value = "/payment/wechat_simulation", method = RequestMethod.POST)
    @ResponseBody
    public JsonResult paymentWechatSimulation(@RequestBody MallOrderPaymentDto dto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jsonResult -> {

            // 为了线上模拟支付 密码为 1946494628469946724L
            if (prop.env.equals(Config.PROD) && 1946494628469946724L != dto.getPassword()) {
                jsonResult.remind("失败",log);
                return;
            }
            if (StringUtils.isBlank(dto.getMallOrderNum())) {
                jsonResult.errorParam("平台订单号 不能为空", log);
                return;
            }
            MallOrder mallOrder = mallOrderRepository.findByOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrder == null) {
                jsonResult.remind(MallOrder.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            if (mallOrder.getActualAmount().longValue() == 0) {
                jsonResult.remind("实付金额为0时，不能使用微信支付",log);
                return;
            }
            mallOrder.setPaymentMethod(PaymentMethod.WECHAT);
            mallOrderRepository.save(mallOrder);

            // 创建平台订单支付
            MallOrderPayment mallOrderPayment = mallOrderPaymentRepository.findByMallOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrderPayment == null) {
                mallOrderPayment = mallOrderPaymentHelper.create(OrderHelper.SINGLEONE.genMallOrderPaymentNumber(), mallOrder.getActualAmount(), mallOrder.getMallId(), mallOrder.getId(), mallOrder.getOrderNum(), customerDto.getId());
                mallOrderPayment = mallOrderPaymentRepository.save(mallOrderPayment);
            }

            if (mallOrderPayment.getStatus() != MallOrderPaymentStatus.WAIT) {
                jsonResult.remind("该订单状态异常,不能继续支付", log);
                return;
            }

            // 添加支付流水
            MallOrderPaymentFlow mallOrderPaymentFlow = new MallOrderPaymentFlow();
            mallOrderPaymentFlow.setFlowNum(OrderHelper.SINGLEONE.genMallOrderPaymentFlowNumber());
            mallOrderPaymentFlow.setPaymentNum(mallOrderPayment.getPaymentNum());
            mallOrderPaymentFlow.setCustomerId(customerDto.getId());
            mallOrderPaymentFlow.setMallOrderId(mallOrder.getId());
            mallOrderPaymentFlow.setMallOrderNum(mallOrder.getOrderNum());
            mallOrderPaymentFlow.setMallId(mallOrder.getMallId());
            mallOrderPaymentFlow.setAmount(mallOrder.getActualAmount());
            mallOrderPaymentFlow.setPaymentMethod(PaymentMethod.WECHAT);
            mallOrderPaymentFlowRepository.save(mallOrderPaymentFlow);

            jsonResult.data = mallOrderPaymentFlow;
        };

        return doing.go(null, customerDto, request, objectMapper, log);
    }

    /**
     * @api {get} /api/v2/payment/choose_way 支付 选择支付方式
     * @apiGroup payment
     * @apiVersion 1.0.0
     * @apiHeader {String} domain <code>必须参数</code>域名
     * @apiHeader {String} userToken <code>必须参数</code>userToken
     *
     * @apiParam {String} mallOrderNum 平台订单号
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     *  "data" :{
     *          "WECHAT",
     *          "BALANCE"
     *  }
     */
    @ResponseBody
    @RequestMapping(value = "/payment/choose_way", method = RequestMethod.GET)
    public JsonResult choosePaymentMethod(MallOrderPaymentDto dto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(dto.getMallOrderNum())) {
                jsonResult.remind("平台订单号 不能为空",log);
                return;
            }
            MallOrder mallOrder = mallOrderRepository.findByOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrder == null) {
                jsonResult.remind("订单不存在",log);
                return;
            }
            CustomerFund customerFund = customerFundRepository.findByCustomerIdAndIsDelete(customerDto.getId(), Whether.NO);
            List<String> paymentMethodList = new ArrayList<>();
            if (customerFund.getAvailableAmount().compareTo(mallOrder.getActualAmount()) >= 0 && mallOrder.getActualAmount().compareTo(BigDecimal.ZERO) == 1) {
                paymentMethodList.add(PaymentMethod.WECHAT.toString());
                paymentMethodList.add(PaymentMethod.BALANCE.toString());
            }
            if (mallOrder.getActualAmount().compareTo(BigDecimal.ZERO) == 0) {
                paymentMethodList.add(PaymentMethod.BALANCE.toString());
            }
            if (customerFund.getAvailableAmount().compareTo(mallOrder.getActualAmount()) == -1) {
                paymentMethodList.add(PaymentMethod.WECHAT.toString());
            }
            jsonResult.data = paymentMethodList;
        };
        return doing.go(request, log);
    }




    /**
     * @api {post} /api/v2/payment/wxapp 支付 小程序支付
     * @apiGroup payment
     * @apiVersion 1.0.0
     * @apiHeader {String} domain <code>必须参数</code>域名
     * @apiHeader {String} userToken <code>必须参数</code>userToken
     *
     * @apiParam {String} mallOrderNum 平台订单号
     * @apiParam {String} orderSource 订单来源，WXAPP:微信小程序；WEXIN:公众号H5
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data":{
     *      "appId":"wxce62f97f15d07734",
     *      "timeStamp":17585882354,'
     *      "nonceStr":"nonceStr",
     *      "package":"prepay_id=xxxxx",
     *      "signType":"MD5",
     *      "paySign":"123xcvdgasfrsfsaf"
     *  }
     * }
     *
     */
    @RequestMapping(value = "/payment/wxapp", method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public JsonResult paymentWxapp(@RequestBody MallOrderPaymentDto dto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        Customer customer = customerRepository.findOne(customerDto.getId());
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(dto.getMallOrderNum())) {
                jsonResult.errorParam("平台订单号 不能为空", log);
                return;
            }
            MallOrder mallOrder = mallOrderRepository.findByOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrder == null) {
                jsonResult.remind(MallOrder.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            if (mallOrder.getActualAmount().doubleValue() == 0) {
                jsonResult.remind("实付金额为0时，不能使用微信支付",log);
                return;
            }


            // 创建平台订单支付
            MallOrderPayment mallOrderPayment = mallOrderPaymentRepository.findByMallOrderNumAndMallId(dto.getMallOrderNum(), customerDto.getMallId());
            if (mallOrderPayment == null) {
                mallOrderPayment = mallOrderPaymentHelper.create(OrderHelper.SINGLEONE.genMallOrderPaymentNumber(), mallOrder.getActualAmount(), mallOrder.getMallId(), mallOrder.getId(), mallOrder.getOrderNum(), customerDto.getId());
                mallOrderPayment = mallOrderPaymentRepository.save(mallOrderPayment);
            }

            if (mallOrderPayment.getStatus() != MallOrderPaymentStatus.WAIT) {
                jsonResult.remind("该订单状态异常,不能继续支付", log);
                return;
            }

            // 添加支付流水
            MallOrderPaymentFlow mallOrderPaymentFlow = new MallOrderPaymentFlow();
            mallOrderPaymentFlow.setFlowNum(OrderHelper.SINGLEONE.genMallOrderPaymentFlowNumber());
            mallOrderPaymentFlow.setPaymentNum(mallOrderPayment.getPaymentNum());
            mallOrderPaymentFlow.setCustomerId(customerDto.getId());
            mallOrderPaymentFlow.setMallOrderId(mallOrder.getId());
            mallOrderPaymentFlow.setMallOrderNum(mallOrder.getOrderNum());
            mallOrderPaymentFlow.setMallId(mallOrder.getMallId());
            mallOrderPaymentFlow.setAmount(mallOrder.getActualAmount());
            mallOrderPaymentFlow.setPaymentMethod(PaymentMethod.WECHAT);
            mallOrderPaymentFlow.setStatus(MallOrderPaymentStatus.WAIT); // 支付中

            mallOrderPaymentFlow = mallOrderPaymentFlowRepository.save(mallOrderPaymentFlow);


            WxMpService wxMpService = wechatHelper.getWxAppService(customerDto.getMallCustomerDomain());
            //默认微信支付

            WechatPaymentAttach wechatPaymentAttach = new WechatPaymentAttach();
            wechatPaymentAttach.setDomain(customerDto.getMallCustomerDomain());
            stringRedisTemplate.opsForValue().set("wechat_payment_code_" + wechatPaymentAttach.getCode(), wechatPaymentAttach.getCode());
            stringRedisTemplate.expire("wechat_payment_code_" + wechatPaymentAttach.getCode(), 2, TimeUnit.DAYS); // 有效时间2天

            WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
            wxPayUnifiedOrderRequest.setBody("微信支付 订单号 : " + mallOrder.getOrderNum());
            wxPayUnifiedOrderRequest.setOutTradeNo(mallOrderPaymentFlow.getFlowNum());
            // 微信 total_fee 单位为分
            wxPayUnifiedOrderRequest.setTotalFee(mallOrder.getActualAmount().multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
            wxPayUnifiedOrderRequest.setSpbillCreateIp(request.getRemoteHost());
            wxPayUnifiedOrderRequest.setNotifyURL(prop.paymentNotifyUrlWechat);
            wxPayUnifiedOrderRequest.setTradeType("JSAPI");
            wxPayUnifiedOrderRequest.setAttach(objectMapper.writeValueAsString(wechatPaymentAttach));
            wxPayUnifiedOrderRequest.setOpenid(customer.getWechatOpenId());

            if (dto.getOrderSource().equals(OrderSource.WXAPP.toString())) {
                WxMpInMemoryConfigStorage wxMpConfigStorage = (WxMpInMemoryConfigStorage) wxMpService.getWxMpConfigStorage();
                MiniAppConfig miniAppConfig = miniAppConfigRepository.findByMallId(mallOrder.getMallId());
                if (miniAppConfig == null) {
                    jsonResult.remind("小程序配置信息不存在", log);
                    return;
                }
//                wxMpConfigStorage.setAppId("wx6015ce54b392fe6f"); // 设置微信公众号的appid
                wxMpConfigStorage.setAppId(miniAppConfig.getAppId());
//                wxMpConfigStorage.setSecret("8b8e2c6fc33e02084793127821485151"); // 设置微信公众号的app corpSecret
                wxMpConfigStorage.setSecret(miniAppConfig.getAppSecret());
                //wxMpConfigStorage.setPartnerId("1348161601");
                wxMpConfigStorage.setPartnerId(miniAppConfig.getMchId());

                String token = "GWH2015GO";
                String sEncodingAESKey = "WtXLiyk28BaGC1ChARcpkgp0FIhqxFTCjNYLm86";
                String partnerKey = "tongjiangyomea91230881MA18XDHA1B";

                wxMpConfigStorage.setToken(token); // 设置微信公众号的token
                wxMpConfigStorage.setAesKey(sEncodingAESKey); // 设置微信公众号的EncodingAESKey
                //wxMpConfigStorage.setPartnerKey(partnerKey);
                wxMpConfigStorage.setPartnerKey(miniAppConfig.getMchSecret());


                wxPayUnifiedOrderRequest.setOpenid(customer.getWxappOpenId());
//                wxMpConfigStorage.setToken(sToken); // 设置微信公众号的token
//                wxMpConfigStorage.setAesKey(sEncodingAESKey); // 设置微信公众号的EncodingAESKey
            }
            //格式：{"timeStamp":"1502437737","package":"prepay_id=wx20170811154857c9e4ab18130128108747","paySign":"2C35EED852AA631EF142F30327355984","appId":"wx14d552a4b57f616c","signType":"MD5","nonceStr":"1502437737434"}
            Map<String, String> callPayParams = wxMpService.getPayService().getPayInfo(wxPayUnifiedOrderRequest);
            String packageStr = callPayParams.get("package");
            if (StringUtils.isNotBlank(packageStr)) {
                String prepay_id = packageStr.substring(packageStr.indexOf("=") + 1);
//                log.info("======================>prepay_id： {}", prepay_id);
//                log.info("======================>mallOrderPaymentFlow.getId()： {}", mallOrderPaymentFlow.getId());

                mallOrderPaymentFlow = mallOrderPaymentFlowRepository.findOne(mallOrderPaymentFlow.getId());
//                log.info("======================>mallOrderPaymentFlow： {}", mallOrderPaymentFlow);

                mallOrderPaymentFlow.setPrepayId(prepay_id);
                mallOrderPaymentFlow.setOrderSource(OrderSource.WXAPP);
                mallOrderPaymentFlowRepository.save(mallOrderPaymentFlow);
            }
//            log.info("======================>call wechat pay information => {}", callPayParams);
            String callPayParamsJson = objectMapper.writeValueAsString(callPayParams);
//            log.info("======================>callPayParamsJson : {}", callPayParamsJson);

            jsonResult.data = callPayParams;
        };

        return doing.go(null, customerDto, request, objectMapper, log);
    }
}
